import { ipcMain, shell, dialog } from 'electron';
import * as fs from 'fs';

export class FileOperationIpcService {
  static registerHandlers() {
    /**
     * 打开文件
     * 使用系统默认应用程序打开指定路径的文件
     * @param event IPC事件对象
     * @param path 文件路径
     * @returns 操作结果
     */
    ipcMain.handle('open-file', async (event, { path }) => {
      try {
        // 检查文件是否存在
        if (!fs.existsSync(path)) {
          return this.createErrorResponse(new Error('文件不存在'), '打开文件失败');
        }
        
        // 打开文件
        await shell.openPath(path);
        return { success: true };
      } catch (error) {
        return this.createErrorResponse(error, '打开文件失败');
      }
    });

    /**
     * 选择文件夹/目录
     * 打开系统文件夹选择对话框
     * @param event IPC事件对象
     * @returns 选择的文件夹路径或取消状态
     */
    ipcMain.handle('select-folder', async (event) => {
      try {
        const result = await dialog.showOpenDialog({
          properties: ['openDirectory'],
          title: '选择文件夹',
          buttonLabel: '选择文件夹'
        });
        
        if (result.canceled) {
          return { canceled: true };
        }
        
        if (result.filePaths && result.filePaths.length > 0) {
          return { success: true, path: result.filePaths[0] };
        }
        
        return this.createErrorResponse(new Error('未选择文件夹'), '选择文件夹失败');
      } catch (error) {
        return this.createErrorResponse(error, '选择文件夹失败');
      }
    });
    
    // 为兼容性保留select-directory别名，指向select-folder处理程序
    ipcMain.handle('select-directory', async (event) => {
      // 重用select-folder的处理逻辑
      return ipcMain.emit('select-folder', event);
    });

    /**
     * 批量重命名文件
     * 根据提供的重命名映射批量重命名文件
     * @param event IPC事件对象
     * @param renameMappings 重命名映射数组，包含原文件名和新文件名
     * @param folderPath 文件夹路径
     * @returns 操作结果
     */
    ipcMain.handle('batch-rename-files', async (event, { renameMappings, folderPath }) => {
      try {
        const path = require('path');
        const fsPromises = fs.promises;
        
        let successCount = 0;
        const errors: string[] = [];
        const totalCount = renameMappings.length;

        // 收集所有目标文件路径，用于检查冲突
        const targetPaths: string[] = [];
        for (let i = 0; i < totalCount; i++) {
          const mapping = renameMappings[i];
          if (!mapping.originalName || !mapping.newName) {
            errors.push(`文件名参数不完整: ${JSON.stringify(mapping)}`);
            continue;
          }
          
          const oldPath = folderPath 
            ? path.join(folderPath, mapping.originalName)
            : mapping.originalName;
          const newPath = folderPath
            ? path.join(folderPath, mapping.newName)
            : mapping.newName;
            
          targetPaths.push(newPath);
        }

        // 检查目标文件名是否有冲突
        const duplicateTargets = targetPaths.filter((item, index) => targetPaths.indexOf(item) !== index);
        if (duplicateTargets.length > 0) {
          const uniqueDuplicates = [...new Set(duplicateTargets)];
          errors.push(`检测到目标文件名冲突: ${uniqueDuplicates.join(', ')}`);
          // 如果有冲突，不执行任何重命名操作
          return this.createErrorResponse(new Error(`目标文件名冲突: ${uniqueDuplicates.join(', ')}`), '批量重命名失败');
        }

        for (let i = 0; i < totalCount; i++) {
          const mapping = renameMappings[i];
          try {
            const originalName = mapping.originalName;
            const newName = mapping.newName;
            
            // 检查必要的参数是否存在
            if (!originalName || !newName) {
              errors.push(`文件名参数不完整: ${JSON.stringify(mapping)}`);
              continue;
            }
            
            const oldPath = folderPath 
              ? path.join(folderPath, originalName)
              : originalName;
            let newPath = folderPath
              ? path.join(folderPath, newName)
              : newName;

            // 检查原文件是否存在
            const exists = await fsPromises.access(oldPath).then(() => true).catch(() => false);
            if (!exists) {
              errors.push(`文件不存在: ${mapping.originalName}`);
              continue;
            }

            // 检查目标文件是否已存在且不是同一文件
            const targetExists = await fsPromises.access(newPath).then(() => true).catch(() => false);
            if (targetExists && oldPath !== newPath) {
              // 生成带有时间戳的文件名以解决冲突
              const extension = path.extname(newPath);
              const baseName = path.basename(newPath, extension);
              const timestamp = new Date().getTime();
              const conflictResolvedPath = path.join(path.dirname(newPath), `${baseName}_${timestamp}${extension}`);
              console.log(`检测到文件名冲突: ${newPath}，将使用: ${conflictResolvedPath}`);
              // 使用解决冲突后的路径
              newPath = conflictResolvedPath;
            }

            // 执行重命名
            await fsPromises.rename(oldPath, newPath);
            successCount++;
            console.log(`重命名文件: ${mapping.originalName} -> ${mapping.newName}`);
            
            // 发送进度更新
            const progress = ((i + 1) / totalCount) * 100;
            event.sender.send('batch-rename-progress', { progress, currentFile: mapping.originalName });
            
          } catch (error) {
            console.error(`重命名文件失败: ${mapping.originalName}`, error);
            const errorMessage = error instanceof Error ? error.message : String(error);
            errors.push(`重命名失败: ${mapping.originalName} - ${errorMessage}`);
          }
        }

        if (successCount === 0) {
          return this.createErrorResponse(new Error('没有文件被重命名'), '批量重命名失败');
        }

        return { 
          success: true, 
          data: { 
            successCount, 
            totalCount,
            errors 
          } 
        };
      } catch (error) {
        return this.createErrorResponse(error, '批量重命名文件失败');
      }
    });

    /**
     * 批量重命名文件（带内容）
     * 处理通过拖放等方式获取的文件，支持保存到原目录或临时目录
     * @param event IPC事件对象
     * @param renameMappings 重命名映射数组，包含oldPath和新名称
     * @param saveToOriginal 是否保存到原目录（替换原文件）
     * @param originalDirectory 原文件目录路径（当saveToOriginal为true时使用）
     * @param isDragDropFiles 是否为拖放文件模式
     * @returns 操作结果
     */
    ipcMain.handle('batch-rename-files-with-content', async (event, { renameMappings, files, saveToOriginal = true, originalDirectory = '', isDragDropFiles = false }) => {
      try {
        const path = require('path');
        const fsPromises = fs.promises; // 使用顶部导入的fs模块
        const os = require('os');

        // (reuse sanitizeFilename from the outer scope)
        
        let successCount = 0;
        const errors: string[] = [];
        const totalCount = renameMappings.length;

        // 检查拖放文件的路径完整性
        if (isDragDropFiles && saveToOriginal) {
          console.log('拖放文件模式，检查路径完整性');
          
          // 检查是否所有文件都有有效的绝对路径
          const hasAllValidPaths = renameMappings.every((mapping: any) => {
            if (!mapping.oldPath) return false;
            return path.isAbsolute(mapping.oldPath);
          });
          
          // 如果不是所有文件都有完整路径，则回退到临时目录模式
          if (!hasAllValidPaths) {
            console.log('部分拖放文件缺少有效的绝对路径，回退到临时目录模式');
            saveToOriginal = false;
          }
        }

        // 收集所有目标文件路径，用于检查冲突
        const targetPaths: string[] = [];
        for (let i = 0; i < totalCount; i++) {
          const mapping = renameMappings[i];
          // 支持新的参数格式（oldPath/newName）和旧的格式（originalName/newName）
          const originalName = mapping.originalName;
          const newName = mapping.newName;
          
          // 检查必要的参数是否存在
          if (!mapping.oldPath && (!originalName || !originalDirectory)) {
            continue; // 在预检查中处理错误
          }
          
          const oldPath = mapping.oldPath || path.join(originalDirectory, originalName);
          
          // 如果使用的是oldPath，提取目录和文件名
          let dirPath, fileName;
          if (mapping.oldPath) {
            dirPath = path.dirname(mapping.oldPath);
            fileName = path.basename(mapping.oldPath);
          } else {
            dirPath = originalDirectory;
            fileName = originalName;
          }
          
          const finalNewName = mapping.newName || newName;
          if (!finalNewName) {
            continue; // 在预检查中处理错误
          }
          
          const newPath = path.join(dirPath, finalNewName);
          targetPaths.push(newPath);
        }

        // 检查目标文件名是否有冲突
        const duplicateTargets = targetPaths.filter((item, index) => targetPaths.indexOf(item) !== index);
        if (duplicateTargets.length > 0) {
          const uniqueDuplicates = [...new Set(duplicateTargets)];
          errors.push(`检测到目标文件名冲突: ${uniqueDuplicates.join(', ')}`);
          // 如果有冲突，不执行任何重命名操作
          return this.createErrorResponse(new Error(`目标文件名冲突: ${uniqueDuplicates.join(', ')}`), '批量重命名失败');
        }

        for (let i = 0; i < totalCount; i++) {
          const mapping = renameMappings[i];
          try {
            // 支持新的参数格式（oldPath/newName）和旧的格式（originalName/newName）
            const originalName = mapping.originalName;
            const newName = mapping.newName;
            
            // 检查必要的参数是否存在
            if (!mapping.oldPath && (!originalName || !originalDirectory)) {
              errors.push(`文件参数不完整: ${JSON.stringify(mapping)}`);
              continue;
            }
            
            const oldPath = mapping.oldPath || path.join(originalDirectory, originalName);
            
            // 如果使用的是oldPath，提取目录和文件名
            let dirPath, fileName;
            if (mapping.oldPath) {
              dirPath = path.dirname(mapping.oldPath);
              fileName = path.basename(mapping.oldPath);
            } else {
              dirPath = originalDirectory;
              fileName = originalName;
            }
            
            const finalNewName = mapping.newName || newName;
            if (!finalNewName) {
              errors.push(`文件名参数不完整: ${JSON.stringify(mapping)}`);
              continue;
            }
            
            let newPath = path.join(dirPath, finalNewName);

            // 检查原文件是否存在
            const exists = await fsPromises.access(oldPath).then(() => true).catch(() => false);
            if (!exists) {
              errors.push(`文件不存在: ${mapping.oldPath || mapping.originalName}`);
              continue;
            }

            // 检查目标文件是否已存在且不是同一文件
            const targetExists = await fsPromises.access(newPath).then(() => true).catch(() => false);
            if (targetExists && oldPath !== newPath) {
              // 生成带有时间戳的文件名以解决冲突
              const extension = path.extname(newPath);
              const baseName = path.basename(newPath, extension);
              const timestamp = new Date().getTime();
              const conflictResolvedPath = path.join(path.dirname(newPath), `${baseName}_${timestamp}${extension}`);
              console.log(`检测到文件名冲突: ${newPath}，将使用: ${conflictResolvedPath}`);
              // 使用解决冲突后的路径
              newPath = conflictResolvedPath;
            }

            // 执行重命名
            await fsPromises.rename(oldPath, newPath);
            successCount++;
            console.log(`重命名文件: ${mapping.oldPath || mapping.originalName} -> ${newPath}`);
            
            // 发送进度更新
            const progress = ((i + 1) / totalCount) * 100;
            event.sender.send('batch-rename-progress', { progress, currentFile: oldPath });
            
          } catch (error) {
            console.error(`重命名文件失败: ${mapping.oldPath || mapping.originalName}`, error);
            const errorMessage = error instanceof Error ? error.message : String(error);
            errors.push(`重命名失败: ${mapping.oldPath || mapping.originalName} - ${errorMessage}`);
          }
        }

        if (successCount === 0) {
          return this.createErrorResponse(new Error('没有文件被重命名'), '批量重命名失败');
        }

        return { 
          success: true, 
          data: { 
            successCount, 
            totalCount,
            errors,
            mode: 'original' // 标识为原目录模式
          } 
        };
      } catch (error) {
        return this.createErrorResponse(error, '批量重命名文件失败');
      }
    });
  }

  /**
   * 统一错误响应格式
   * @param error 错误对象
   * @param defaultMessage 默认错误消息
   * @returns 标准化的错误响应对象
   */
  private static createErrorResponse(error: any, defaultMessage: string): { success: false; error: string } {
    const errorMessage = error instanceof Error ? error.message : String(error || defaultMessage);
    console.error(defaultMessage, error);
    return { success: false, error: errorMessage };
  }
}